package com.tianji.learning.service.impl;

import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.api.dto.leanring.LearningRecordFormDTO;
import com.tianji.common.status.LessonStatus;
import com.tianji.common.utils.*;
import com.tianji.learning.entity.LearningLesson;
import com.tianji.learning.entity.LearningRecord;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.utils.LearningRecordDelayTaskHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author author
 * @since 2023-05-26
 */
@Service
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    @Autowired
    private ILearningLessonService lessonService;
    @Autowired
    private CourseClient courseClient;
    @Autowired
    private LearningRecordDelayTaskHandler taskHandler;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String RECORD_KEY = "RECORD_KEY_{}_{}";
    /**
     * 查询当前用户指定课程的学习进度
     *
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询当前课程信息
        LearningLesson learningLesson = lessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        AssertUtils.isNotNull(learningLesson,"查询不到课程！");

        LearningLessonDTO dto = BeanUtils.copyBean(learningLesson, LearningLessonDTO.class);
        //3.查询小节信息，并构造成LearningRecordDto对象
        List<LearningRecord> learningRecordsList = this.lambdaQuery()
                .eq(LearningRecord::getLessonId, dto.getId())
                .eq(LearningRecord::getUserId, userId)
                .list();
        //4.包装DTO返回
        List<LearningRecordDTO> list = BeanUtils.copyList(learningRecordsList, LearningRecordDTO.class);
        dto.setRecords(list);
        return dto;
    }

    /**
     * 提交学习记录
     *
     * @param formDTO
     */
    @Override
    public void addLearningRecord(LearningRecordFormDTO formDTO) {
        //1.获取登录用户
        Long userId = UserContext.getUser();
        Integer sectionType = formDTO.getSectionType();
        //2.判断标志是否考试

        boolean bool ;
        if (sectionType == 2) {
            //2.1 考试
            bool =  addExam(formDTO,userId);
        }else{
            //2.2 判断学习记录是否存在？更新：新增
            bool = addVideo(formDTO,userId);
        }
        if (bool){
            //3.课表已学习小节数量+1
        //课表信息
        LearningLesson learningLesson = this.lessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getId, formDTO.getLessonId())
                .one();
        //已学习小节
        int learningNum = learningLesson.getLearnedSections() + 1;
            //3.1查询课程详细信息
            CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(learningLesson.getCourseId(), false, false);

            AssertUtils.isNotNull(cInfo,"查询不到课程！");

            //3.2如果已完成课程数 >= 小节总数 ？课程已完成：不操作
            bool = learningNum >= cInfo.getSectionNum();

            //数量+1
            this.lessonService.lambdaUpdate()
                    .set(LearningLesson::getLearnedSections, learningNum)
                    .set(LearningLesson::getLatestSectionId,formDTO.getSectionId())
                    .set(LearningLesson::getLatestLearnTime, LocalDate.now())
                    .set(LearningLesson::getUpdateTime, LocalDate.now())
                    .set(LearningLesson::getStatus, bool?LessonStatus.FINISHED:LessonStatus.LEARNING)
                    .eq(LearningLesson::getId,learningLesson.getId())
                    .update();
        }


    }


    private Boolean addVideo(LearningRecordFormDTO dto, Long userId) {
        LearningRecord record  = queryOldRecord(dto.getLessonId(), dto.getSectionId());
        //2.判断是否时长超过50% 是？修改学习状态：无操作
        Boolean bool = dto.getDuration() < dto.getMoment() * 2;
        if(bool){
            //2.1 更新学习记录
            this.lambdaUpdate()
                    .set(LearningRecord::getFinished,true)
                    .set(LearningRecord::getFinishTime,LocalDateTime.now())
                    .set(LearningRecord::getUpdateTime,LocalDateTime.now())
                    .eq(LearningRecord::getId,record.getId())
                    .update();
            //2.2 删除缓存
            taskHandler.cleanRecordCache(dto.getLessonId(),record.getId());
        }else{
            record.setMoment(dto.getMoment());
            taskHandler.addLearningRecordTask(record);
        }
        return bool;
    }

    private LearningRecord queryOldRecord(Long lessonId, Long sectionId) {
        // 1.查询缓存
        LearningRecord record = taskHandler.readRecordCache(lessonId, sectionId);
        // 2.如果命中，直接返回
        if (record != null) {
            return record;
        }
        // 3.未命中，查询数据库
        record = lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
        // 4.写入缓存
        taskHandler.writeRecordCache(record);
        return record;
    }


    private LearningRecord addRecord(LearningRecordFormDTO dto, Long userId) {
        //新增学习记录：视频
        LearningRecord learningRecord = LearningRecord.builder()
                .lessonId(dto.getLessonId())
                .sectionId(dto.getSectionId())
                .userId(userId)
                .moment(dto.getMoment())
                .createTime(LocalDateTime.now())
                .build();
        //新增
        this.save(learningRecord);
        return learningRecord;
    }

    private Boolean addExam(LearningRecordFormDTO dto, Long userId) {
        //新增学习记录：考试
        LearningRecord learningRecord = LearningRecord.builder()
                .lessonId(dto.getLessonId())
                .sectionId(dto.getLessonId())
                .userId(userId)
                .moment(dto.getMoment())
                .createTime(LocalDateTime.now())
                .finishTime(LocalDateTime.now())
                .finished(true)
                .build();
        //新增
        this.save(learningRecord);
        return true;
    }
}
